package esi.t2no1.dao.message;

import static esi.t2no1.util.DaoUtil.extractFirst;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

/**
 * Implementation of {@link MessageDAO}
 * 
 * @author Kaarel Jõgeva
 */
public class MessageDAOImpl implements MessageDAO {

	private SimpleJdbcTemplate simpleJdbcTemplate;
	private SimpleJdbcInsert log;

	public static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";

	private static RowMapper<MessageDTO> messageMapper = new RowMapper<MessageDTO>() {

		@Override
		public MessageDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
			MessageDTO m = new MessageDTO();
			m.setId(rs.getLong("id"));
			try {
				m.setLogdate(new SimpleDateFormat(DATEFORMAT).parse(rs.getString("logdate")));
			} catch (ParseException e) {
				m.setLogdate(rs.getDate("logdate")); // Failover
			}
			m.setInbound(rs.getBoolean("inbound"));
			m.setTransactionId(rs.getInt("transactionId"));
			m.setMisc(rs.getString("misc"));
			m.setPayload(rs.getString("payload"));
			return m;
		}
	};

	@Override
	public List<MessageDTO> getTodayMessages() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);

		return getMessages(cal.getTime(), new Date());
	}

	@Override
	public List<MessageDTO> getMessages(Date fromDate, Date toDate) {
		return getMessages(fromDate, toDate, null);
	}

	@Override
	public List<MessageDTO> getMessages(boolean inbound) {
		return getMessages(null, null, inbound);
	}

	@Override
	public List<MessageDTO> getMessages(Date fromDate, Date toDate, Boolean inbound) {
		StringBuilder sql = new StringBuilder("select * from messagelog where ");
		Map<String, Object> params = new HashMap<String, Object>(4);

		if (inbound != null) {
			sql.append(":inbound = ? and ");
			params.put("inbound", inbound.toString());
		}

		DateFormat df = new SimpleDateFormat(DATEFORMAT);
		if (fromDate == null) {
			Calendar cal = Calendar.getInstance();
			cal.add(Calendar.DATE, -1);
			fromDate = cal.getTime();
		}

		if (toDate == null) {
			toDate = new Date();
		}

		sql.append("logdate between :fromDate and :toDate ");
		params.put("fromDate", df.format(fromDate));
		params.put("toDate", df.format(toDate));
		sql.append("order by id desc");

		return simpleJdbcTemplate.query(sql.toString(), messageMapper, params);
	}

	@Override
	public List<MessageDTO> getTransactionMessages(int messageTransactionId) {
		String sql = "select * from messagelog where transactionId = ? order by logdate asc";
		return simpleJdbcTemplate.query(sql, messageMapper, messageTransactionId);
	}

	@Override
	public MessageDTO getMessage(int id) {
		String sql = "select * from messagelog where id = ? limit 1";
		return extractFirst(simpleJdbcTemplate.query(sql, messageMapper, id));
	}
	
	@Override
	public int logMessage(Map<String, Object> logParts) {
		return log.execute(logParts);
	}

	@Autowired
	public void setDataSource(DataSource dataSource) {
		simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
		log = new SimpleJdbcInsert(dataSource).withTableName("messagelog")
				.usingGeneratedKeyColumns("id", "logdate");
	}

}
